﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.IO;
using SevenZip;
using System.Reflection;

namespace HiganUI
{ 
    using Ini;
    using BrightIdeasSoftware;
    using System.Collections;

    public partial class Form1 : Form
    {  
        IniFile iniFile;
        bool autoSizeRomListColumns = false;

        //roms list struct for lists
        protected class Roms
        {
            public int  Id {set;  get; }
            public int  ParentId {set;  get; }
            public string Title {set;  get; }
            public string FullPath { set; get; }
            public string Image { set; get; }
            public string Company { set; get; }
            public string Language { set; get; }
            public string Notes { set; get; }
            public bool   Tree { set; get; }
        }

        public Form1( splashScreen sp)
        {
            InitializeComponent();

            //7zipdll
            string applicationPath = Path.Combine( Path.GetDirectoryName( Assembly.GetExecutingAssembly().Location ), "7z.dll" );
            SevenZipExtractor.SetLibraryPath( applicationPath );

            //ini file
            string p = System.Reflection.Assembly.GetExecutingAssembly().Location;
            p = p.Substring( 0, p.Length - 3 ) + "ini";
            iniFile = new IniFile( p );

            populateListViews();
            populatemenuCheckStates();
            loadSettings();
            //make a timer for small lists, no need for a timer with large file lists. 
            sp.Hide();
        }

        protected override bool ProcessCmdKey( ref Message msg, Keys keyData )
        {//key watcher
            if ( keyData == ( Keys.Control | Keys.Q ) ) { Application.Exit(); }
            return base.ProcessCmdKey( ref msg, keyData );
        }

        private void Form1_FormClosing( object sender, FormClosingEventArgs e )
        {//clean up.
            saveSettings();
            File.SetAttributes( iniFile.fullFileName(), FileAttributes.ReadOnly );//set flag
        }

        private void pauseWhenInactiveToolStripMenuItem_Click( object sender, EventArgs e )
        {
            iniFile.IniWriteValue( "menuitem", "pauseWhenInactive", pauseWhenInactiveToolStripMenuItem.CheckState.ToString() );
        }

        private void startGameInFullScrenModeToolStripMenuItem_Click( object sender, EventArgs e )
        {
            iniFile.IniWriteValue( "menuitem", "startGameInFullScrenMode", startGameInFullScrenModeToolStripMenuItem.CheckState.ToString() );
        }
        private void autoSizeRomListColumnsToolStripMenuItem_Click( object sender, EventArgs e )
        {
            iniFile.IniWriteValue( "menuitem", "autoSizeRomListColumnsMode", autoSizeRomListColumnsToolStripMenuItem.CheckState.ToString() );
            loadSettings();
            //need to apple auto to all collumns and all tabs if user goes back to auto size.
            if ( autoSizeRomListColumnsToolStripMenuItem.CheckState == CheckState.Checked)
            {
                for ( int i=0; i < 6;i++ )  SNES_listView.AutoResizeColumn( i, ColumnHeaderAutoResizeStyle.HeaderSize );
                for ( int i=0; i < 6;i++ )  NES_listView.AutoResizeColumn( i, ColumnHeaderAutoResizeStyle.HeaderSize );
                for ( int i=0; i < 6;i++ )  GBA_listView.AutoResizeColumn( i, ColumnHeaderAutoResizeStyle.HeaderSize );
                for ( int i=0; i < 6;i++ )  GB_listView.AutoResizeColumn( i, ColumnHeaderAutoResizeStyle.HeaderSize );
            }
        }
        private void skipGBABloatToolStripMenuItem_Click( object sender, EventArgs e )
        {//flag for the emulator and public domain files, helps speed at load.
            iniFile.IniWriteValue( "menuitem", "skipGBABloatMode", skipGBABloatToolStripMenuItem.CheckState.ToString() );
        }


        private void loadGameToolStripMenuItem_Click( object sender, EventArgs e )
        {
            string Chosen_file = "";
            openFile.Title = "Select a Rom";
            openFile.FileName = "";
            openFile.Filter = "SNES Images|*.s?c|NES Images|*.nes|Game Boy Images|*.gb?|7z|*.7z|zip|*.zip|rar|*.rar";
            if ( openFile.ShowDialog() == DialogResult.Cancel )
            {
                // MessageBox.Show( "Operation Cancelled" );   
            }
            else
            {
                Chosen_file = openFile.FileName;
                MessageBox.Show( "File loaded" );
            }
        }

        private void inputToolStripMenuItem_Click( object sender, EventArgs e )
        {
            inputSetup newChild = new inputSetup();
            DialogResult dr = new DialogResult();
            dr = newChild.ShowDialog();        
        }

        private void aboutToolStripMenuItem_Click( object sender, EventArgs e )
        {
            AboutBox1 newChild = new AboutBox1();
            newChild.Show();
        }

        private void exitToolStripMenuItem_Click( object sender, EventArgs e )
        {
            Application.Exit();
        }

        private void romPathsToolStripMenuItem_Click( object sender, EventArgs e )
        {
            romPaths newChild = new romPaths();
            DialogResult dr = new DialogResult();
            dr = newChild.ShowDialog();
            if ( dr == DialogResult.OK ) populateListViews();            
        }
        private void populateListViews()
        {
            FileInfo[] files;
            DirectoryInfo di;

            //as of now there is no easy way to find multiple file types, so I use *.* ( coudl use where clause )
            if ( iniFile.IniReadValue( "rompaths", "SNES" )  != "" )
            {
                di = new DirectoryInfo(  iniFile.IniReadValue( "rompaths", "SNES" ) );
                files = di.GetFiles("*.*");
                populateDetails( files, SNES_listView );
                
            }
            if ( iniFile.IniReadValue( "rompaths", "NES" )  != "" )
            {
                di = new DirectoryInfo( iniFile.IniReadValue( "rompaths", "NES" ) );
                files = di.GetFiles( "*.*" );
                populateDetails( files, NES_listView ); 
            }
            if ( iniFile.IniReadValue( "rompaths", "GBA" )  != "" )
            {
                di = new DirectoryInfo( iniFile.IniReadValue( "rompaths", "GBA" ) );
                files = di.GetFiles( "*.*" );
                populateDetails( files, GBA_listView );
            }
            if ( iniFile.IniReadValue( "rompaths", "GB" ) != "" )
            {
                di = new DirectoryInfo( iniFile.IniReadValue( "rompaths", "GB" ) );
                files = di.GetFiles( "*.*" );
                populateDetails( files, GB_listView );
            }

        }
        private void populatemenuCheckStates()
        {                                                                                        
            if ( iniFile.IniReadValue( "menuitem", "pauseWhenInactive" ) == "Checked" ) pauseWhenInactiveToolStripMenuItem.CheckState = CheckState.Checked; else pauseWhenInactiveToolStripMenuItem.CheckState = CheckState.Unchecked;
            if ( iniFile.IniReadValue( "menuitem", "startGameInFullScrenMode" ) == "Checked" ) startGameInFullScrenModeToolStripMenuItem.CheckState = CheckState.Checked; else pauseWhenInactiveToolStripMenuItem.CheckState = CheckState.Unchecked;
            if ( iniFile.IniReadValue( "menuitem", "autoSizeRomListColumnsMode" ) == "Checked" ) autoSizeRomListColumnsToolStripMenuItem.CheckState = CheckState.Checked; else autoSizeRomListColumnsToolStripMenuItem.CheckState = CheckState.Unchecked;
            if ( iniFile.IniReadValue( "menuitem", "skipGBABloatMode" ) == "Checked" ) skipGBABloatToolStripMenuItem.CheckState = CheckState.Checked; else skipGBABloatToolStripMenuItem.CheckState = CheckState.Unchecked;
        }
        private void loadSettings()
        {
            if (SNES_listView.Columns.Count > 0 && autoSizeRomListColumnsToolStripMenuItem.CheckState != CheckState.Checked )
            {
                if (iniFile.IniReadValue("tabs", "snesTitle") != "" && Convert.ToInt32(iniFile.IniReadValue("tabs", "snesTitle  ")) > 0) SNES_listView.Columns[0].Width = Convert.ToInt32(iniFile.IniReadValue("tabs", "snesTitle  "));
                if (iniFile.IniReadValue("tabs", "snesFullPath") != "" && Convert.ToInt32(iniFile.IniReadValue("tabs", "snesFullPath")) > 0) SNES_listView.Columns[1].Width = Convert.ToInt32(iniFile.IniReadValue("tabs", "snesFullPath"));
                if (iniFile.IniReadValue("tabs", "snesImage") != "" && Convert.ToInt32(iniFile.IniReadValue("tabs", "snesImage  ")) > 0) SNES_listView.Columns[2].Width = Convert.ToInt32(iniFile.IniReadValue("tabs", "snesImage  "));
                if (iniFile.IniReadValue("tabs", "snesCompany") != "" && Convert.ToInt32(iniFile.IniReadValue("tabs", "snesCompany")) > 0) SNES_listView.Columns[3].Width = Convert.ToInt32(iniFile.IniReadValue("tabs", "snesCompany"));
                if (iniFile.IniReadValue("tabs", "snesLanguage") != "" && Convert.ToInt32(iniFile.IniReadValue("tabs", "snesLanguage")) > 0) SNES_listView.Columns[4].Width = Convert.ToInt32(iniFile.IniReadValue("tabs", "snesLanguage"));
                if (iniFile.IniReadValue("tabs", "snesNotes") != "" && Convert.ToInt32(iniFile.IniReadValue("tabs", "snesNotes")) > 0) SNES_listView.Columns[5].Width = Convert.ToInt32(iniFile.IniReadValue("tabs", "snesNotes"));
                SNES_listView.Refresh();
            }
            if (NES_listView.Columns.Count > 0 && autoSizeRomListColumnsToolStripMenuItem.CheckState != CheckState.Checked)
            {
                if ( iniFile.IniReadValue( "tabs", "nesTitle"    ) != "" && Convert.ToInt32( iniFile.IniReadValue( "tabs", "nesTitle"    )  ) > 0) NES_listView.Columns[ 0 ].Width = Convert.ToInt32( iniFile.IniReadValue( "tabs","nesTitle"    ) );
                if ( iniFile.IniReadValue( "tabs", "nesFullPath" ) != "" && Convert.ToInt32( iniFile.IniReadValue( "tabs", "nesFullPath" )  ) > 0) NES_listView.Columns[ 1 ].Width = Convert.ToInt32( iniFile.IniReadValue( "tabs","nesFullPath" ) );
                if ( iniFile.IniReadValue( "tabs", "nesImage"    ) != "" && Convert.ToInt32( iniFile.IniReadValue( "tabs", "nesImage"    )  ) > 0) NES_listView.Columns[ 2 ].Width = Convert.ToInt32( iniFile.IniReadValue( "tabs","nesImage"    ) );
                if ( iniFile.IniReadValue( "tabs", "nesCompany"  ) != "" && Convert.ToInt32( iniFile.IniReadValue( "tabs", "nesCompany"  )  ) > 0) NES_listView.Columns[ 3 ].Width = Convert.ToInt32( iniFile.IniReadValue( "tabs","nesCompany"  ) );
                if ( iniFile.IniReadValue( "tabs", "nesLanguage" ) != "" && Convert.ToInt32( iniFile.IniReadValue( "tabs", "nesLanguage" )  ) > 0) NES_listView.Columns[ 4 ].Width = Convert.ToInt32( iniFile.IniReadValue( "tabs","nesLanguage" ) );
                if ( iniFile.IniReadValue( "tabs", "nesNotes"    ) != "" && Convert.ToInt32( iniFile.IniReadValue( "tabs", "nesNotes"    )  ) > 0) NES_listView.Columns[ 5 ].Width = Convert.ToInt32( iniFile.IniReadValue( "tabs","nesNotes"    ) );
                NES_listView.Refresh();
            }
            if (GBA_listView.Columns.Count > 0 && autoSizeRomListColumnsToolStripMenuItem.CheckState != CheckState.Checked)
            {                                                                                                                                                                                                                            
                if ( iniFile.IniReadValue( "tabs", "gbaTitle"    ) != "" && Convert.ToInt32( iniFile.IniReadValue( "tabs", "gbaTitle"    )  ) > 0) GBA_listView.Columns[ 0 ].Width = Convert.ToInt32( iniFile.IniReadValue( "tabs","gbaTitle"    ) );
                if ( iniFile.IniReadValue( "tabs", "gbaFullPath" ) != "" && Convert.ToInt32( iniFile.IniReadValue( "tabs", "gbaFullPath" )  ) > 0) GBA_listView.Columns[ 1 ].Width = Convert.ToInt32( iniFile.IniReadValue( "tabs","gbaFullPath" ) );
                if ( iniFile.IniReadValue( "tabs", "gbaImage"    ) != "" && Convert.ToInt32( iniFile.IniReadValue( "tabs", "gbaImage"    )  ) > 0) GBA_listView.Columns[ 2 ].Width = Convert.ToInt32( iniFile.IniReadValue( "tabs","gbaImage"    ) );
                if ( iniFile.IniReadValue( "tabs", "gbaCompany"  ) != "" && Convert.ToInt32( iniFile.IniReadValue( "tabs", "gbaCompany"  )  ) > 0) GBA_listView.Columns[ 3 ].Width = Convert.ToInt32( iniFile.IniReadValue( "tabs","gbaCompany"  ) );
                if ( iniFile.IniReadValue( "tabs", "gbaLanguage" ) != "" && Convert.ToInt32( iniFile.IniReadValue( "tabs", "gbaLanguage" )  ) > 0) GBA_listView.Columns[ 4 ].Width = Convert.ToInt32( iniFile.IniReadValue( "tabs","gbaLanguage" ) );
                if ( iniFile.IniReadValue( "tabs", "gbaNotes"    ) != "" && Convert.ToInt32( iniFile.IniReadValue( "tabs", "gbaNotes"    )  ) > 0) GBA_listView.Columns[ 5 ].Width = Convert.ToInt32( iniFile.IniReadValue( "tabs","gbaNotes"    ) );
                GBA_listView.Refresh();
            }
            if (GB_listView.Columns.Count > 0 && autoSizeRomListColumnsToolStripMenuItem.CheckState != CheckState.Checked)
            {
                if (iniFile.IniReadValue("tabs", "gbTitle") != "" && Convert.ToInt32(iniFile.IniReadValue("tabs", "gbTitle")) > 0) GB_listView.Columns[0].Width = Convert.ToInt32(iniFile.IniReadValue("tabs", "gbTitle"));
                if (iniFile.IniReadValue("tabs", "gbFullPath") != "" && Convert.ToInt32(iniFile.IniReadValue("tabs", "gbFullPath")) > 0) GB_listView.Columns[1].Width = Convert.ToInt32(iniFile.IniReadValue("tabs", "gbFullPath"));
                if (iniFile.IniReadValue("tabs", "gbImage") != "" && Convert.ToInt32(iniFile.IniReadValue("tabs", "gbImage")) > 0) GB_listView.Columns[2].Width = Convert.ToInt32(iniFile.IniReadValue("tabs", "gbImage"));
                if (iniFile.IniReadValue("tabs", "gbCompany") != "" && Convert.ToInt32(iniFile.IniReadValue("tabs", "gbCompany")) > 0) GB_listView.Columns[2].Width = Convert.ToInt32(iniFile.IniReadValue("tabs", "gbCompany"));
                if (iniFile.IniReadValue("tabs", "gbLanguage") != "" && Convert.ToInt32(iniFile.IniReadValue("tabs", "gbLanguage")) > 0) GB_listView.Columns[4].Width = Convert.ToInt32(iniFile.IniReadValue("tabs", "gbLanguage"));
                if (iniFile.IniReadValue("tabs", "gbTNotes") != "" && Convert.ToInt32(iniFile.IniReadValue("tabs", "gbTNotes")) > 0) GB_listView.Columns[5].Width = Convert.ToInt32(iniFile.IniReadValue("tabs", "gbTNotes"));
                GB_listView.Refresh();
            }
        }
        private void saveSettings()
        {
            if (SNES_listView.Columns.Count > 0)
            {
                iniFile.IniWriteValue("tabs", "snesTitle", SNES_listView.Columns[0].Width.ToString());
                iniFile.IniWriteValue("tabs", "snesFullPath", SNES_listView.Columns[1].Width.ToString());
                iniFile.IniWriteValue("tabs", "snesImage", SNES_listView.Columns[2].Width.ToString());
                iniFile.IniWriteValue("tabs", "snesCompany", SNES_listView.Columns[3].Width.ToString());
                iniFile.IniWriteValue("tabs", "snesLanguage", SNES_listView.Columns[4].Width.ToString());
                iniFile.IniWriteValue("tabs", "snesNotes", SNES_listView.Columns[5].Width.ToString());
            }
            if (NES_listView.Columns.Count > 0)
            {
                iniFile.IniWriteValue("tabs", "nesTitle", NES_listView.Columns[0].Width.ToString());
                iniFile.IniWriteValue("tabs", "nesFullPath", NES_listView.Columns[ 1 ].Width.ToString() );
                iniFile.IniWriteValue("tabs", "nesImage", NES_listView.Columns[2].Width.ToString());
                iniFile.IniWriteValue("tabs", "nesCompany", NES_listView.Columns[3].Width.ToString());
                iniFile.IniWriteValue("tabs", "nesLanguage", NES_listView.Columns[4].Width.ToString());
                iniFile.IniWriteValue("tabs", "nesNotes", NES_listView.Columns[5].Width.ToString());
            }
            if (GBA_listView.Columns.Count > 0)
            {
                iniFile.IniWriteValue("tabs", "gbaTitle", GBA_listView.Columns[0].Width.ToString());
                iniFile.IniWriteValue("tabs", "gbaFullPath", GBA_listView.Columns[1].Width.ToString());
                iniFile.IniWriteValue("tabs", "gbaImage", GBA_listView.Columns[2].Width.ToString());
                iniFile.IniWriteValue("tabs", "nesCompany", GBA_listView.Columns[3].Width.ToString());
                iniFile.IniWriteValue("tabs", "gbaLanguage", GBA_listView.Columns[4].Width.ToString());
                iniFile.IniWriteValue("tabs", "gbaNotes", GBA_listView.Columns[5].Width.ToString());
            }
            if (GB_listView.Columns.Count > 0)
            {
                iniFile.IniWriteValue("tabs", "gbTitle", GB_listView.Columns[0].Width.ToString());
                iniFile.IniWriteValue("tabs", "gbFullPath", GB_listView.Columns[1].Width.ToString());
                iniFile.IniWriteValue("tabs", "gbImage", GB_listView.Columns[2].Width.ToString());
                iniFile.IniWriteValue("tabs", "gbCompany", GB_listView.Columns[3].Width.ToString());
                iniFile.IniWriteValue("tabs", "gbLanguage", GB_listView.Columns[4].Width.ToString());
                iniFile.IniWriteValue("tabs", "gbNotes", GB_listView.Columns[5].Width.ToString());
            }
        }
        private void populateDetails( FileInfo[] fs, DataTreeListView l )
        {
            List<Roms> roms = new List<Roms>();
            int index=1;
           
            foreach ( FileInfo file in fs )
            { //Console.WriteLine( file.FullName );
                if (file.Extension.Length < 1) break; 
                string ext = file.Extension.Substring( 1, file.Extension.Length - 1 );
                switch (file.Extension.ToLower() )
                {
                    case ".sfc":
                    case ".smc":
                    case ".nes":
                    case ".gb":
                    case ".gba":
                    case ".gbc":
                        if ( l.Tag.ToString().IndexOf( "{"+ext.ToUpper()+"}" ) != -1 )//tag will hold the data that accepted. Can be multip extentions
                            roms.Add( new Roms { Tree = false, Id = index, ParentId = 0, Title = file.Name.Substring( 0, file.Name.LastIndexOf( "." ) ),FullPath = file.FullName, Image = "...", Company = "Nintendo", Language = "USA", Notes = "......." } );
                    break;

                    case ".zip":
                    case ".rar":
                    case ".7z":
                    SevenZipExtractor arc = new SevenZipExtractor( file.FullName );
                    if ( arc.ArchiveFileNames.Count > 1 && ( skipGBABloatToolStripMenuItem.CheckState == CheckState.Checked && file.Name.IndexOf( "Domain (" ) == -1 && file.Name.IndexOf( "Emulation (" ) == -1 ) )//add from archives
                        {//multiple files
                            //root
                            roms.Add( new Roms {Tree = true, Id = index, ParentId = 0,  Title = file.Name.Substring( 0, file.Name.LastIndexOf( "." )), FullPath = file.FullName, Image = "...", Company = "Nintendo", Language = "USA", Notes = "......." } );
                            //children
                            List <string> files = new List<string>();
                            for ( int i=0; i < arc.ArchiveFileNames.Count; i++)
                                if ( l.Tag.ToString().IndexOf( "{" + arc.ArchiveFileNames[ i ].Substring( arc.ArchiveFileNames[ i ].LastIndexOf( "." ) + 1 ).ToUpper() + "}" ) != -1 )//tag will hold the data that accepted. Can be multip extentions
                                    roms.Add( new Roms { Tree = false, Id = index, ParentId = index, Title = arc.ArchiveFileNames[i].Substring( 0, arc.ArchiveFileNames[i].LastIndexOf( "." )), FullPath = file.FullName, Image = "...", Company = "Nintendo", Language = "USA", Notes = "......." } );
                        
                        }
                        else
                        {//single fle
                            if ( l.Tag.ToString().IndexOf( "{" + arc.ArchiveFileNames[ 0 ].Substring( arc.ArchiveFileNames[ 0 ].LastIndexOf( "." ) + 1 ).ToUpper() + "}" ) != -1 )//tag will hold the data that accepted. Can be multip extentions
                                roms.Add( new Roms {Tree = false, Id = index, ParentId = 0,  Title =arc.ArchiveFileNames[0].Substring( 0, arc.ArchiveFileNames[0].LastIndexOf( "." )),  FullPath = file.FullName, Image = "...", Company = "Nintendo", Language = "USA", Notes = "......." } );
                          
                        }
                    break;
                }

                index++;
            }
            l.CanExpandGetter = delegate(object x) {var r = ( Roms ) x; return r.Tree;};
            l.ParentKeyAspectName = "ParentId";
            l.KeyAspectName = "Id";
            l.RootKeyValue = 0;
            l.ShowKeyColumns = false;
            l.DataSource = roms;
            //defult to autosize. user can override this.
            l.AutoResizeColumn( 0, ColumnHeaderAutoResizeStyle.HeaderSize );
            l.AutoResizeColumn( 1, ColumnHeaderAutoResizeStyle.HeaderSize );
            l.AutoResizeColumn( 2, ColumnHeaderAutoResizeStyle.HeaderSize );
            l.AutoResizeColumn( 3, ColumnHeaderAutoResizeStyle.HeaderSize );
            l.AutoResizeColumn( 4, ColumnHeaderAutoResizeStyle.HeaderSize );

            l.Columns[ 6 ].Dispose();//no longer need this
        }


        private void SNES_listView_DoubleClick( object sender, EventArgs e )
        {
            MessageBox.Show( "load game: " + SNES_listView.Items[ SNES_listView.SelectedIndex ].SubItems[2].Text );
        }

        private void Form1_Load( object sender, EventArgs e )
        {

        }
    }
}
